import { WebSocket } from 'ws'
import i18n from '@/i18n'
import { META_ROUTER_PREFIX } from '@apps/meta/app-const'
import { ActionSocketService, Assist } from '@libs/lhy-common'
import { WsExceptionFilter } from '@libs/lhy-core'
import { UseFilters } from '@nestjs/common'
import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'
import { MetaPlatformApiService } from '../../meta-platform-api/meta-platform-api.service'
import { MetaRealtimeDataWsPushAction, MetaRealtimeDataWsReceiveAction } from './entity/meta-realtime-data-ws-action'
import { MetaRealtimeDataWsCode } from './entity/meta-realtime-data-ws-code'
import { MetaRealtimeDataWsSetParamDto } from './entity/meta-realtime-data-ws-set-param.dto'
import { MetaRealtimeDataWsUrlParam } from './entity/meta-realtime-data-ws-url-param'

@UseFilters(WsExceptionFilter)
@WebSocketGateway({ path: `${META_ROUTER_PREFIX}/ws/realtime_data` })
export class MetaRealtimeDataWsService extends ActionSocketService<
  MetaRealtimeDataWsUrlParam,
  MetaRealtimeDataWsPushAction | MetaRealtimeDataWsReceiveAction,
  MetaRealtimeDataWsCode
> {
  constructor(readonly platformApiService: MetaPlatformApiService) {
    super({
      async auth(param, client) {
        Assist.threw(
          !param.bindDataSourcePaths?.length,
          i18n.t('app-meta.meta-realtime-data-ws.meta-realtime-data-ws.1215092-0')
        )

        await platformApiService.requestWsAuth({
          platform: param.platform,
          token: param.userToken,
          uniqueId: param.uniqueId,
          paths: param.bindDataSourcePaths,
        })
      },
      authOnConnected: false,
    })
  }

  @SubscribeMessage(MetaRealtimeDataWsReceiveAction.SetParams)
  handleSetParams(@ConnectedSocket() client: WebSocket, @MessageBody() data: MetaRealtimeDataWsSetParamDto) {
    const url = this.clientDataWeakMap.get(client)?.url

    if (url) {
      this.logger.debug(
        () => `receive SetParams [url=${this.clientDataWeakMap.get(client)?.url}]: ` + JSON.stringify(data)
      )

      this.auth(data, url, client)
    } else {
      this.sendMessage(client, {
        action: MetaRealtimeDataWsPushAction.Prompt,
        code: MetaRealtimeDataWsCode.InvalidClient,
        data: i18n.t('app-meta.meta-realtime-data-ws.meta-realtime-data-ws.1215092-1'),
      })
      client.close()

      this.logger.info(() => i18n.t('app-meta.meta-realtime-data-ws.meta-realtime-data-ws.1215092-2'))
    }
  }
}
